import datetime
from django.conf import settings
from django.db import models
from django.contrib.auth.models import User

class Page(models.Model):

  PUBLICITY_CHOICES = (
    ('public', 'Public'),
    ('internal', 'Internal'),
    ('private', 'Private'),
  )

  EDITABILITY_CHOICES = (
    ('open', 'Open'),
    ('protected', 'Protected'),
  )

  title = models.CharField(max_length=50, unique=True)
  text = models.TextField()
  updated = models.DateTimeField(auto_now=True, default=datetime.datetime.today())
  is_public = models.CharField(max_length=8, choices=PUBLICITY_CHOICES, default='public')
  is_editable = models.CharField(max_length=9, choices=EDITABILITY_CHOICES, default='open')
  is_deleted = models.BooleanField(default=False, editable=False)
  author = models.ForeignKey(User, editable=False)
  tags = models.ManyToManyField("Tag", null=True, blank=True)

  def __unicode__(self):
    return self.title

  def is_viewable(self, user):
    if self.is_public == 'public':
      if self.is_deleted:
        # Deleted
        return (False, 3)
      else:
        return (True, 0)
    elif user.is_authenticated():
      if self.is_public == 'internal':
        if self.is_deleted:
          return (False, 3)
        else:
          return (True, 0)
      if self.is_public == 'private' and self.author.id == user.id:
        return (True, 0)
      else:
        # Not Allowed
        return (False, 1)
    else:
      # Need Login
      return (False, 2)

  def is_protected(self, user):
    if self.is_editable == 'open':
      # Open
      try:
        lock = Lock.objects.get(page=self)
        return self.check_locked(user, lock)
      except Lock.DoesNotExist:
        return (False, '')
    else:
      # Protected
      if self.author == user:
        try:
          lock = Lock.objects.get(page=self)
          return self.check_locked(user, lock)
        except Lock.DoesNotExist:
          return (False, '')
      else:
        return (True, 'You are not allowed to edit this page.')

  def lock(self, user):
    try:
      l = Lock.objects.get(page=self)
      l.delete()
    except Lock.DoesNotExist:
      pass
    l = Lock(page=self, author=user)
    l.save()

  def unlock(self, user):
    try:
      l = Lock.objects.get(page=self)
      l.delete()
    except Lock.DoesNotExist:
      pass

  def check_locked(self, user, lock):
    if datetime.datetime.today() > lock.when_locked + settings.LOCK_DURATION:
      # Lock expired
      lock.delete()
      return (False, '')
    else:
      # Lock is effective
      message = 'This page is locked.<br/>' + lock.author.username + ' is editing this page since ' + lock.when_locked.strftime("%Y-%m-%d %H:%M.")
      if settings.HARD_LOCK:
        return (True, message)
      else:
        return (False, message)

  def delete(self, *args, **kwargs):
    self.is_deleted = True
    super(Page, self).save(args, **kwargs)
    for tag in self.tags.all():
      tag.page_count()
      if tag.count == 0:
        tag.delete()
      else:
        tag.save()
    self.tags = []

  def update_tag_count(self, old_tags, cleanup=False):
    updated_tags = list(self.tags.all())
    for tag in old_tags:
      if not tag in updated_tags:
        updated_tags.append(tag)
    for tag in updated_tags:
      tag.page_count()
      if tag.count == 0 and cleanup:
        tag.delete()
      else:
        tag.save()


class Tag(models.Model):

  text = models.CharField(max_length=20, unique=True)
  count = models.IntegerField(default=0)

  def __unicode__(self):
    return self.text

  def page_count(self):
    c = 0
    for p in Page.objects.filter(is_deleted=False):
      if self in p.tags.all():
        c = c + 1
    self.count = c


class History(models.Model):

  PUBLICITY_CHOICES = (
    ('public', 'Public'),
    ('internal', 'Internal'),
    ('private', 'Private'),
  )

  ACTION_CHOICES = (
    ('save', 'Save'),
    ('delete', 'Delete'),
    ('revert', 'Revert'),
  )

  page = models.ForeignKey(Page)
  action = models.CharField(max_length=6, choices=ACTION_CHOICES, default='save')
  title = models.CharField(max_length=50)
  text = models.TextField(editable=False)
  is_public = models.CharField(max_length=8, choices=PUBLICITY_CHOICES, default='public')
  updated = models.DateTimeField()
  author = models.ForeignKey(User)

  def __unicode__(self):
    return self.title


class Lock(models.Model):

  page = models.ForeignKey(Page, unique=True)
  author = models.ForeignKey(User)
  when_locked = models.DateTimeField(auto_now=True, default=datetime.datetime.today(), editable=True)

  def __unicode__(self):
    return self.page.title

